package com.af.system.util;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalAdjusters;

/**
 * 日历工具类
 *
 * @author : zhenyun.su
 * @since : 2024/1/17
 * 上一周， 月同周， 年同周， 上月， 年同月， 都可以根据对应同期日期来获取
 */

public final class AfCalendar {
    //今天
    public static LocalDate today(){
        return LocalDate.now();
    };

    // 下一天， 默认为明天
    public static LocalDate nextDay(LocalDate date) {
        return date.plusDays(1);
    }

    // 上一天， 默认为昨天
    public static LocalDate lastDay(LocalDate date) {
        return date.minusDays(1);
    }

    /**
     * 当周第一天
     *
     * @param date 给定日期
     * @param dayOfWeek 星期几， 默认为周一， 也可周日是第一天， 则参数DayOfWeek.SUNDAY
     * @return 给定日期所在周的第一天
     */
    public static LocalDate firstDayOfWeek(LocalDate date, DayOfWeek dayOfWeek) {
        return date.with(TemporalAdjusters.previousOrSame(dayOfWeek==null? DayOfWeek.MONDAY : dayOfWeek));
    }

    /**
     * 当周最后一天
     *
     * @param date 给定日期
     * @param dayOfWeek 星期几， 默认为周日最后一天， 也可周六是最后一天， 则参数DayOfWeek.SATURDAY
     * @return 给定日期所在周的最后一天
     */
    public static LocalDate lastDayOfWeek(LocalDate date, DayOfWeek dayOfWeek) {
        return date.with(TemporalAdjusters.nextOrSame(dayOfWeek==null? DayOfWeek.SUNDAY : dayOfWeek));
    }

    // 当月第一天
    public static LocalDate firstDayOfMonth(LocalDate date) {
        return date.with(TemporalAdjusters.firstDayOfMonth());
    }

    // 当月最后一天
    public static LocalDate lastDayOfMonth(LocalDate date) {
        return date.with(TemporalAdjusters.lastDayOfMonth());
    }

    // 当季第一天
    public static LocalDate firstDayOfQuarter(LocalDate date) {
        int quarter = date.get(IsoFields.QUARTER_OF_YEAR); // 获取当前季度（1-4）
        return date.with(TemporalAdjusters.firstDayOfYear())
                .plusMonths(3 * (quarter - 1))
                .with(TemporalAdjusters.firstDayOfMonth());
    }

    // 当季最后一天
    public static LocalDate lastDayOfQuarter(LocalDate date) {
        int quarter = date.get(IsoFields.QUARTER_OF_YEAR); // 获取当前季度（1-4）
        return date.with(TemporalAdjusters.firstDayOfYear())
                .plusMonths(3 * (quarter)).minusDays(1);
    }

    //当年第一天
    public static LocalDate firstDayOfYear(LocalDate date) {
        return date.with(TemporalAdjusters.firstDayOfYear());
    }
    //当年最后一天
    public static LocalDate lastDayOfYear(LocalDate date) {
        return date.with(TemporalAdjusters.lastDayOfYear());
    }

    //当天的季度
    public static int quarter(LocalDate date) {
        return date.get(IsoFields.QUARTER_OF_YEAR);
    }

    //当天的年份
    public static int year(LocalDate date) {
        return date.getYear();
    }
    //当天所在月份
    public static int month(LocalDate date) {
        return date.getMonthValue();
    }
    // 所在月中天
    public static int day(LocalDate date) {
        return date.getDayOfMonth();
    }
    //所在年中天， 从1到365，或366天
    public static int dayOfYear(LocalDate date) {
        return date.getDayOfYear();
    }
    // 所在周中天， 从1到7天
    public static int dayOfWeek(LocalDate date) {
        return date.getDayOfWeek().getValue();
    }

    // 所在年中的周， 从1到52周
    public static int weekOfYear(LocalDate date) {
        return date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
    }

    // 周，月，季度及年同比所在日期

    //上个月的同一天
    public static LocalDate dayOfLastMonth(LocalDate date) {
        return date.minusMonths(1);
    }
    //上个周的同一天
    public static LocalDate dayOfLastWeek(LocalDate date) {
        return date.minusDays(7);
    }
    public static LocalDate dayOfLastQuarter(LocalDate date) {
        return date.minusMonths(3);
    }
    // 获取当月的天数
    public static int lengthOfMonth(LocalDate date) {
        return date.lengthOfMonth();
    }

    //去年同期日期，减去一年，得到去年同期的同一天
    public static LocalDate sameDayLastYear(LocalDate date) {
        return date.minus(1, ChronoUnit.YEARS);
    }
    //前年同期日期
    public static LocalDate sameDayLastTwoYear(LocalDate date) {
        return date.minus(2, ChronoUnit.YEARS);
    }

    //上月同期日期，减去一月，得到上月同期的同一天
    public static LocalDate sameDayLastMonth(LocalDate date) {
        return date.minus(1, ChronoUnit.MONTHS);
    }
    //上月同期日期，减去一月，得到上月同期的同一天
    public static LocalDate sameDayLastWeek(LocalDate date) {
        return date.minus(1, ChronoUnit.WEEKS);
    }

    public static void main(String[] args) {
        // LocalDate date = LocalDate.of(2023, 12, 12);
        LocalDate date = today();
        System.out.println(AfCalendar.firstDayOfYear(date));
        System.out.println(AfCalendar.lastDayOfYear(date));
        System.out.println(AfCalendar.firstDayOfQuarter(date));
        System.out.println(AfCalendar.lastDayOfQuarter(date));
        System.out.println(AfCalendar.firstDayOfMonth(date));
        System.out.println(AfCalendar.lastDayOfMonth(date));
        System.out.println(AfCalendar.firstDayOfWeek(date, DayOfWeek.MONDAY));
        System.out.println(AfCalendar.lastDayOfWeek(date, DayOfWeek.SUNDAY));
        System.out.println(AfCalendar.year(date));
        System.out.println(AfCalendar.quarter(date));
        System.out.println(AfCalendar.month(date));
        System.out.println(AfCalendar.day(date));
        System.out.println(AfCalendar.weekOfYear(date));
        System.out.println(AfCalendar.dayOfWeek(date));
        System.out.println(AfCalendar.dayOfYear(date));
        System.out.println(AfCalendar.nextDay(date));
        System.out.println(AfCalendar.lastDay(date));
        System.out.println(AfCalendar.today());
        System.out.println(AfCalendar.dayOfLastMonth(date));
        System.out.println(AfCalendar.dayOfLastWeek(date));
        System.out.println(AfCalendar.dayOfLastQuarter(date));
        System.out.println(AfCalendar.lengthOfMonth(date));
        System.out.println(AfCalendar.sameDayLastYear(date));
        System.out.println(AfCalendar.sameDayLastTwoYear(date));
        System.out.println(AfCalendar.sameDayLastMonth(date));
        System.out.println(AfCalendar.sameDayLastWeek(date));
    }
}
